package com.yungu.swift.order.processor;

import com.alibaba.dubbo.config.annotation.Reference;
import com.yungu.swift.assets.driver.model.dto.DriverDto;
import com.yungu.swift.assets.driver.service.DriverService;
import com.yungu.swift.assets.passenger.model.dto.PassengerCouponDto;
import com.yungu.swift.assets.passenger.service.PassengerCouponService;
import com.yungu.swift.assets.passenger.service.PassengerService;
import com.yungu.swift.base.ResponseData;
import com.yungu.swift.constants.FinanceConstant;
import com.yungu.swift.order.model.vo.PayVo;
import com.yungu.swift.system.finance.model.dto.FinanceInviteRewardDto;
import com.yungu.swift.system.finance.service.FinanceInviteRewardService;
import com.yungu.swift.system.marketing.model.dto.MarketingCouponDto;
import com.yungu.swift.system.marketing.model.dto.MarketingGiftDto;
import com.yungu.swift.system.marketing.model.dto.MarketingInviteLogDto;
import com.yungu.swift.system.marketing.service.MarketingCouponService;
import com.yungu.swift.system.marketing.service.MarketingGiftService;
import com.yungu.swift.system.marketing.service.MarketingInviteLogService;
import com.yungu.swift.system.sys.model.dto.SysAccountDriverDto;
import com.yungu.swift.system.sys.model.dto.SysAccountPlatformDto;
import com.yungu.swift.system.sys.service.SysAccountDriverService;
import com.yungu.swift.system.sys.service.SysAccountPlatformService;
import com.yungu.swift.utils.MapUtils;
import com.yungu.swift.utils.ParamUtil;
import com.yungu.swift.utils.StringUtils;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.collections4.map.HashedMap;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.transaction.support.TransactionTemplate;

import java.math.BigDecimal;
import java.util.*;
import java.util.concurrent.CompletableFuture;


/**
 * 司机邀请的乘客完成第一单订单之后获取司机邀请礼包的处理器
 *
 * @author Zerrion
 * @date 2017/9/14 20:29
 */
@Slf4j
@Component
public class PassengerGiftProcessor implements PayProcessor {

    private static final Logger logger = LoggerFactory.getLogger(PassengerGiftProcessor.class);

    @Autowired
    private TransactionTemplate transactionTemplate;
    @Reference
    private MarketingInviteLogService marketingInviteLogService;
    @Reference
    private DriverService driverService;
    @Reference
    private MarketingCouponService marketingCouponService;
    @Reference
    private MarketingGiftService marketingGiftService;
    @Reference
    private PassengerService passengerService;
    @Reference
    private PassengerCouponService passengerCouponService;
    @Reference
    private SysAccountDriverService sysAccountDriverService;
    @Reference
    private SysAccountPlatformService sysAccountPlatformService;
    @Reference
    private FinanceInviteRewardService financeInviteRewardService;

    @Override
    public void process(PayVo payVo) {
        if (ParamUtil.defaultIfNull(payVo.getPassengerVo().getOrderCount(), 0) != 0) {
            return;
        }
        // 司机邀请乘客，完成首单现金奖励
        firstOrderDriverReward(payVo);
        // 乘客邀请乘客，完成首单获取优惠券信息
        firstOrderPassengerReward(payVo);
    }

    private void firstOrderPassengerReward(PayVo payVo) {
        Map<String, Object> build = MapUtils.build(4);
        build.put("invitee", payVo.getPassengerVo().getMobile());
        //邀请类型
        build.put("inviterType", 1);
        //被邀请类型
        build.put("inviteeType", 1);
        MarketingInviteLogDto inviteLogDto = marketingInviteLogService.get(build).getData();
        if (inviteLogDto == null) {
            logger.warn("获取不到乘客邀请记录，invitee：{}", payVo.getPassengerVo().getMobile());
            return;
        }
        if (inviteLogDto.getInviterReceiveStatus() == 1) {
            logger.warn("邀请者 invitee：{}, 已经领取了奖励", payVo.getPassengerVo().getMobile());
            return;
        }

        List<String> inviterUuids = passengerService.getUuids(MapUtils.build("mobile", inviteLogDto.getInviter()))
                .getData();
        if (CollectionUtils.isEmpty(inviterUuids)) {
            logger.warn("获取不到乘客(邀请者)信息，mobile：{}", inviteLogDto.getInviter());
            return;
        }
        Map<String, Object> marketingMap = new HashedMap(4);
        marketingMap.put("type", 2);
        marketingMap.put("status", 1);
        MarketingGiftDto marketingGift = marketingGiftService.get(marketingMap).getData();
        if (marketingGift == null) {
            logger.warn("获取不到乘客邀请乘客礼包信息");
            return;
        }
        // 定义邀请者优惠券集合（保存到数据库中）
        List<PassengerCouponDto> inviterCouponDtoList = new ArrayList<>();
        //邀请者 发送优惠券
        List<MarketingCouponDto> inviterCouponList = new ArrayList<>();

        if (marketingGift.getInviteRewardMethod() == 1 && marketingGift.getGetMode() == 1) {
            // 获取邀请者自定义礼包
            Map<String, Object> couponMap = new HashedMap();
            couponMap.put("giftUuid", marketingGift.getUuid());
            couponMap.put("giftType", 2);
            couponMap.put("couponSubType", 1);
            inviterCouponList = marketingCouponService.getActiveCouponsByMap(couponMap).getData();
            inviteLogDto.setInviterReceiveStatus(1);
        }

        //邀请人获取优惠券
        for (MarketingCouponDto marketingCouponDto : inviterCouponList) {
            PassengerCouponDto inviterCouponDto = new PassengerCouponDto();
            inviterCouponDto.setUuid(StringUtils.buildUUID());
            inviterCouponDto.setAppid(payVo.getAppid());
            inviterCouponDto.setStatus(1);
            inviterCouponDto.setCreateOn(new Date());
            inviterCouponDto.setPassengerUuid(inviterUuids.get(0));
            inviterCouponDto.setSysCouponUuid(marketingCouponDto.getUuid());
            inviterCouponDto.setCityNames(marketingCouponDto.getCityNames());
            inviterCouponDto.setCityUuids(marketingCouponDto.getCityUuids());
            //设置优惠券过期时间
            setCouponExpireTime(marketingCouponDto, inviterCouponDto);
            inviterCouponDtoList.add(inviterCouponDto);
        }
        if (!inviterCouponDtoList.isEmpty()) {
            //批量新增乘客优惠券
            CompletableFuture.runAsync(() -> passengerCouponService.addBatch(inviterCouponDtoList));
        }
        marketingInviteLogService.edit(inviteLogDto);
    }

    private void firstOrderDriverReward(PayVo payVo) {
        // 营销邀请记录
        Map<String, Object> inviteMap = new HashMap<>(4);
        inviteMap.put("invitee", payVo.getPassengerVo().getMobile());
        //邀请类型（1 乘客 2司机）
        inviteMap.put("inviterType", 2);
        //被邀请类型（1 乘客 2 司机）
        inviteMap.put("inviteeType", 1);
        MarketingInviteLogDto inviteLogDto = marketingInviteLogService.get(inviteMap).getData();
        if (inviteLogDto == null) {
            logger.warn("乘客：{}，获取不到邀请记录", payVo.getPassengerVo().getMobile());
            return;
        }
        if (inviteLogDto.getCashBack() == null) {
            logger.warn("邀请记录没有收现金额,uuid：{}", inviteLogDto.getUuid());
            return;
        }
        // 获取邀请乘客的司机
        DriverDto driverDto = driverService.get(MapUtils.build("mobile", inviteLogDto.getInviter())).getData();
        if (driverDto == null) {
            logger.warn("获取不到邀请司机信息，mobile:{}", inviteLogDto.getInviter());
            return;
        }
        // 平台账户信息
        ResponseData<SysAccountPlatformDto> getByAppid = sysAccountPlatformService.getByAppid(payVo.getAppid());
        if (!getByAppid.isSuccess() || getByAppid.getData() == null) {
            logger.warn("获取不到平台账户信息，appid:{}", payVo.getAppid());
            return;
        }
        SysAccountPlatformDto platformAccount = getByAppid.getData();
        // 司机账户信息
        ResponseData<SysAccountDriverDto> getByUuid = sysAccountDriverService.get(driverDto.getUuid());
        if (!getByUuid.isSuccess() || getByUuid.getData() == null) {
            logger.warn("获取不到司机账户信息，driverUuid:{}", payVo.getDriverVo().getUuid());
            return;
        }
        SysAccountDriverDto driverAccount = getByUuid.getData();
        BigDecimal canFrowardBalance = Optional.of(driverAccount.getCanFrowardBalance()).orElse(BigDecimal.ZERO);

        //增加司机邀请奖励流水
        FinanceInviteRewardDto inviteRewardDto = new FinanceInviteRewardDto();
        inviteRewardDto.setUuid(StringUtils.buildUUID());
        inviteRewardDto.setAppid(driverDto.getAppid());
        inviteRewardDto.setFinanceNumber(StringUtils.buildUUID());
        inviteRewardDto.setCourse(FinanceConstant.DRIVER_INVITE_PASSENGER_INVITE_REWARD);
        inviteRewardDto.setAmount(inviteLogDto.getCashBack());
        inviteRewardDto.setBusinessUuid(inviteLogDto.getUuid());
        inviteRewardDto.setDescription("司机邀请乘客获得" + inviteLogDto.getCashBack() + "元奖励");
        // 平台-> 司机
        inviteRewardDto.setFinanceInflow(driverDto.getUuid());
        inviteRewardDto.setFinanceOutflow(platformAccount.getUuid());
        inviteRewardDto.setStartBalance(canFrowardBalance);
        canFrowardBalance = canFrowardBalance.add(inviteLogDto.getCashBack());
        inviteRewardDto.setFinalBalance(canFrowardBalance);
        inviteRewardDto.setCreateOn(new Date());
        inviteRewardDto.setCreateBy(driverDto.getUuid());
        financeInviteRewardService.add(inviteRewardDto);

        //修改邀请司机的可提现余额
        driverAccount.setCanFrowardBalance(canFrowardBalance);
        driverAccount.setUpdateOn(new Date());

        //修改平台奖励累积
        BigDecimal rewardAccumulate = Optional.of(platformAccount.getRewardAccumulate()).orElse(BigDecimal.ZERO);
        rewardAccumulate = rewardAccumulate.add(inviteLogDto.getCashBack());
        platformAccount.setRewardAccumulate(rewardAccumulate);
        platformAccount.setUpdateOn(new Date());

        CompletableFuture.runAsync(() -> {
            transactionTemplate.execute(transactionStatus -> {
                sysAccountDriverService.edit(driverAccount);
                sysAccountPlatformService.edit(platformAccount);
                return Boolean.TRUE;
            });
        }).whenComplete((t, throwable) -> logger.info("乘客完成首单：{}，司机获得现金奖励成功", payVo.getOrderUuid()));
    }

    private void setCouponExpireTime(MarketingCouponDto marketingCouponDto, PassengerCouponDto
            passengerCouponDto) {
        //设置优惠券过期时间
        if (1 == marketingCouponDto.getTermType()) {
            passengerCouponDto.setUseStartTime(marketingCouponDto.getUseStartTime());
            Calendar c = Calendar.getInstance();
            c.setTime(marketingCouponDto.getUseEndTime());
            c.set(Calendar.MINUTE, 59);// 分
            c.set(Calendar.SECOND, 59);// 秒
            c.set(Calendar.MILLISECOND, 0);// 毫秒
            c.set(Calendar.HOUR_OF_DAY, 23);// 时
            passengerCouponDto.setUseEndTime(c.getTime());
        }
        if (2 == marketingCouponDto.getTermType()) {
            Calendar c = Calendar.getInstance();
            c.set(Calendar.HOUR_OF_DAY, 0);// 时
            c.set(Calendar.MINUTE, 0);// 分
            c.set(Calendar.SECOND, 0);// 秒
            c.set(Calendar.MILLISECOND, 0);// 毫秒
            passengerCouponDto.setUseStartTime(c.getTime());
            c.set(Calendar.HOUR_OF_DAY, 23);// 时
            c.set(Calendar.MINUTE, 59);// 分
            c.set(Calendar.SECOND, 59);// 秒
            c.set(Calendar.MILLISECOND, 0);// 毫秒
            c.add(Calendar.DATE, marketingCouponDto.getUseExpireTime() - 1);
            passengerCouponDto.setUseEndTime(c.getTime());
        }
    }
}
